package hamaster.jpbc.mgr;

import hamaster.jpbc.crypt.CryptIO;
import hamaster.jpbc.crypt.impl.IBENativeCryptIOImpl;
import hamaster.jpbc.exception.CryptException;
import hamaster.jpbc.gui.DecryptPanel;
import hamaster.jpbc.pbc.PBCDriver;
import hamaster.jpbc.pbc.io.IBCIOException;
import hamaster.jpbc.pbc.io.ID;
import hamaster.jpbc.pbc.io.IDIO;
import hamaster.jpbc.pbc.io.SimpleIDFileIOImpl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Properties;

import javax.swing.JOptionPane;

public class AsymmetricDecryptManager extends SymmetricDecryptManager {

	public AsymmetricDecryptManager(File meta, File idFile, File saveFolder,
			DecryptPanel callback) {
		super(meta, idFile, saveFolder, callback);
	}

	@Override
	public void run() {
		ID id;
		try {
			IDIO idio = new SimpleIDFileIOImpl(idFile);
			id = idio.load();
		} catch (IBCIOException e) {
			callback.message(Messages.getString("SymmetricDecryptManager.cannotReadID"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
			return;
		}
		Properties metadata = new Properties();
		try {
			metadata.load(new FileInputStream(meta));
		} catch (IOException e) {
			callback.message(Messages.getString("SymmetricDecryptManager.cannotReadMeta"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
			return;
		}
		String crypto = new String(PBCDriver.unhex(metadata.getProperty(SymmetricEncryptManager.SYMMETRIC_KEY)));
		if (!"IBC".equalsIgnoreCase(crypto)) { //$NON-NLS-1$
			super.run();
			return;
		}
		String filename;
		String cipherName;
		try {
			filename = new String(PBCDriver.unhex(metadata.getProperty(SymmetricEncryptManager.PLAIN_FILE_NAME)), "UTF-8"); //$NON-NLS-1$
			cipherName = new String(PBCDriver.unhex(metadata.getProperty(SymmetricEncryptManager.CIPHER_NAME_KEY)), "UTF-8"); //$NON-NLS-1$
		} catch (UnsupportedEncodingException e) {
			filename = new String(PBCDriver.unhex(metadata.getProperty(SymmetricEncryptManager.PLAIN_FILE_NAME)));
			cipherName = new String(PBCDriver.unhex(metadata.getProperty(SymmetricEncryptManager.CIPHER_NAME_KEY)));
		}
		File plainMessage = new File(saveFolder, filename);
		File cipher = new File(meta.getParentFile(), cipherName);
		if (!cipher.exists()) {
			String format = Messages.getString("AsymmetricDecryptManager.3"); //$NON-NLS-1$
			callback.message(String.format(format, filename), JOptionPane.ERROR_MESSAGE);
			return;
		}
		if (!cipher.canRead()) {
			String format = Messages.getString("AsymmetricDecryptManager.4"); //$NON-NLS-1$
			callback.message(String.format(format, filename), JOptionPane.ERROR_MESSAGE);
			return;
		}
		CryptIO io = new IBENativeCryptIOImpl(plainMessage.getAbsolutePath(), id.getPrivateKey());
		io.setProgressListener(callback);
		try {
			io.decrypt(cipher, null);
		} catch (IOException e) {
			callback.message(Messages.getString("SymmetricDecryptManager.cannotWritePlain"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
			return;
		} catch (CryptException e) {
			callback.message(Messages.getString("SymmetricDecryptManager.cryptoError"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
			return;
		}
		if ("true".equalsIgnoreCase(metadata.getProperty(SymmetricEncryptManager.SIGNED_MARK))) { //$NON-NLS-1$
			callback.message(Messages.getString("SymmetricDecryptManager.verifySignature"), JOptionPane.INFORMATION_MESSAGE); //$NON-NLS-1$
			callback.enableVerify(plainMessage, metadata);
		} else {
			callback.message(Messages.getString("SymmetricDecryptManager.decryptComplete"), JOptionPane.INFORMATION_MESSAGE); //$NON-NLS-1$
		}
	}
}
